Skip to content

feat(kilo-app): add KiloClaw chat with Stream Chat#1674

Merged
iscekic merged 48 commits intomainfrom
feature/kiloclaw-mobile-chat
Mar 31, 2026
Merged

feat(kilo-app): add KiloClaw chat with Stream Chat#1674
iscekic merged 48 commits intomainfrom
feature/kiloclaw-mobile-chat

Conversation

@iscekic
Copy link
Copy Markdown
Contributor

@iscekic iscekic commented Mar 27, 2026

Summary

  • Adds real-time chat with KiloClaw bot in the mobile app using stream-chat-react-native SDK
  • Header shows bot online/offline status indicator and a settings gear button that navigates to the dashboard
  • Handles all states: disabled (machine not running), loading, error, upgrade-required, and active chat
  • Uses the existing getStreamChatCredentials tRPC procedure — no backend changes needed

Test plan

  • Open the app, navigate to a KiloClaw instance
  • Verify chat shows "Chat is available when the machine is running." when instance is stopped
  • Start the instance, verify chat connects and shows messages
  • Verify bot online/offline indicator updates in the header
  • Verify settings gear icon navigates to the dashboard
  • Send a message, verify bot responds in real-time
  • Kill the app and reopen — verify token refresh works (chat reconnects)

@iscekic iscekic self-assigned this Mar 27, 2026
@kilo-code-bot
Copy link
Copy Markdown
Contributor

kilo-code-bot bot commented Mar 27, 2026

Code Review Summary

Status: 3 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 3
SUGGESTION 0
Issue Details (click to expand)

WARNING

File Line Issue
kilo-app/src/components/kiloclaw/chat.tsx 251 Passing keyboardVerticalOffset={headerHeight} on Android replaces the Stream Expo default offset, so the composer can jump too high and leave a gap above the keyboard.
Other Observations (not in diff)

Issues found in unchanged code that cannot receive inline comments:

File Line Issue
kilo-app/src/components/kiloclaw/chat.tsx 208 The cleanup path still never calls disconnectUser(), so leaving the screen can keep the Stream websocket connected in the background until chat mounts again.
pnpm-workspace.yaml 68 minimumReleaseAgeExclude still bypasses the quarantine for every Expo and React Native package, weakening the repo-wide supply-chain guardrail.

Fix these issues in Kilo Cloud

Files Reviewed (8 files)
  • kilo-app/app.config.js - 0 issues
  • kilo-app/src/components/kiloclaw/chat-hooks.ts - 0 issues
  • kilo-app/src/components/kiloclaw/chat.tsx - 2 issues
  • package.json - 0 issues
  • patches/@gorhom__bottom-sheet@5.1.8.patch - 0 issues
  • patches/stream-chat-expo@8.13.7.patch - 0 issues
  • pnpm-lock.yaml - 0 issues
  • pnpm-workspace.yaml - 1 issue

Reviewed by gpt-5.4-20260305 · 220,042 tokens

iscekic added 2 commits March 30, 2026 17:04
- Move chat from tab navigator to standalone stack screen so tab bar
  doesn't cover the message input
- Show machine name in the chat header instead of generic "Chat"
- Pass bottom safe area inset to Channel for proper home indicator spacing
- Add horizontal/vertical padding for screen edge curvature
- Set keyboardVerticalOffset=0 (no native nav header)
- Fix hot reload crash by not disconnecting singleton StreamChat client
  in effect cleanup
- Enable Sentry in dev mode for crash visibility
- Remove LogBox i18next suppression (no longer needed)
Style MessageInput via Stream Chat theme to keep the separator
edge-to-edge while padding the input content. Extract chat hooks
to a separate file and improve keyboard handling.

Add NSPhotoLibraryUsageDescription so tapping the attachment
button shows the permission prompt instead of crashing.
iscekic added 5 commits March 30, 2026 18:49
Map app design tokens to Stream Chat's theme color keys so chat
backgrounds, message bubbles, date headers, and input match the
rest of the app in dark mode.
Use "chat/[instance-id]" instead of "chat" in the (app) Stack layout
to match the actual route path. Restore stream-chat LogBox.ignoreLogs
that were lost in a prior merge.
stream-chat-expo auto-registers Expo-compatible native handlers (audio,
file picker, etc.), fixing the "No recorder instance" runtime error.
Also removes 7 peer deps that stream-chat-expo bundles internally.
…p config

Remove @gorhom/bottom-sheet and react-native-nitro-modules (no longer
needed after stream-chat-expo migration). Keep @react-native-community/netinfo
as it's still a required peer dep of stream-chat-react-native-core.
…tale expo-doctor config

These were unused config plugins. Also re-add stream-chat (JS client)
which is directly imported for the StreamChat class and Channel type.
…etection

keyboardWillShow/Hide are iOS-only events, so keyboard state never
updated on Android, causing wrong bottom inset in the chat layout.
iscekic added 3 commits March 31, 2026 13:27
…at input

Replace custom KeyboardAvoidingView + useKeyboardAwareBottomInset with
Stream Chat's built-in keyboard handling. Pass bottomInset for safe area
and measure header height for keyboardVerticalOffset so the input clears
the Android navigation bar.
…gure permissions

Add expo-audio, expo-document-picker, expo-image-picker, expo-media-library,
expo-sharing, and expo-video with their Expo config plugins. Add iOS infoPlist
entries for camera, microphone, photo library, and photo library save access.
Copy link
Copy Markdown
Contributor

@catrielmuller catrielmuller left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @iscekic, could you please add a "Thinking..." message to the bot's responses when the content is initially empty? This would enhance the user experience. Currently, OpenClaw first sends an empty message, and then updates it once it receives a response from the LLM. You can refer to this example for guidance: https://github.com/Kilo-Org/kilocode/pull/7960/changes#diff-5bbb72df3cce4225d35536a23aa77bb95da0a0eabeda91f54077c9628f7db6b8R25.
Thank you!

iscekic added 7 commits March 31, 2026 13:54
…undingClientRect

stream-chat-react-native-core ships a postinstall that patches
@gorhom/bottom-sheet to add typeof guards before calling
unstable_getBoundingClientRect. pnpm doesn't reliably re-run this
cross-package postinstall on re-links, so use patchedDependencies
to apply it at the store level instead.
Video thumbnails in the attachment picker used raw ph:// asset URIs
which RCTImageLoader cannot resolve. Use the already-resolved local
file URI instead, matching what is done for the main asset URI.
@iscekic
Copy link
Copy Markdown
Contributor Author

iscekic commented Mar 31, 2026

Hi @iscekic, could you please add a "Thinking..." message to the bot's responses when the content is initially empty? This would enhance the user experience. Currently, OpenClaw first sends an empty message, and then updates it once it receives a response from the LLM. You can refer to this example for guidance: Kilo-Org/kilocode#7960 (changes). Thank you!

I'm not seeing empty responses from my short testing. Merging, saving your comment to check later.

@iscekic iscekic enabled auto-merge (squash) March 31, 2026 13:10
@iscekic iscekic merged commit 6b98ef6 into main Mar 31, 2026
33 checks passed
@iscekic iscekic deleted the feature/kiloclaw-mobile-chat branch March 31, 2026 13:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants